﻿/**
 * author:  Martin Hrabos
 * year:    2016
 * email:   hrabosmartin@gmail.com
 * 
 * FIT Brno University of Technology / ASCR Brno
 */

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;

namespace CorrCL
{
    /*
     * Class related to result rectangles
     * Stores result values and visual objects
     */
    public class ResultPoint
    {
        private Rectangle rect;
        private List<float[]> blocks;
        private float[] resultSignal;
        private float medianValue;
        private float maxValue;
        private int indexMaxValue;
        private float minValue;
        private int indexMinValue;
        private Color resultColor;
        public readonly static int MARGIN_LEFT = 20;
        public readonly static int MARGIN_TOP = 20;
        public readonly static int RECT_PADDING = 5;
        public readonly static int RECT_HEIGHT = 24;
        public readonly static int RECT_WIDTH = 24;
        public long originSize;
        public string label1;
        public string label2;
        public string sourceFile;

        // Create new result point 
        public ResultPoint(List<float[]> blocks, int row, int col, int LONGEST_LABEL_LENGTH, string label1, string label2)
        {
            this.blocks = blocks;
            this.label1 = label1;
            this.label2 = label2;

            // Generate signal from blocks
            resultSignal = getSignalfromBlocks();


            this.maxValue = resultSignal.Max();
            this.indexMaxValue = Array.IndexOf(resultSignal, maxValue);
            // Get min value
            this.minValue = resultSignal.Min();
            this.indexMinValue = Array.IndexOf(resultSignal, minValue);
            // Calculate median
            float[] tmpArr = new float[resultSignal.Length];


            // Create deep copy of an array
            for (int i = 0; i < tmpArr.Length; i++)
            {
                tmpArr[i] = resultSignal[i];
            }
            Array.Sort(tmpArr);
            int mid = tmpArr.Length / 2;
            if (tmpArr.Length % 2 == 0)
            {
                medianValue = (tmpArr[mid - 1] + tmpArr[mid]) / 2;
            }
            else
            {
                medianValue = tmpArr[mid / 2];
            }

            // Create rectangle object
            rect = new Rectangle(col * RECT_WIDTH + col * RECT_PADDING + MARGIN_LEFT + LONGEST_LABEL_LENGTH,
                                 row * RECT_HEIGHT + row * RECT_PADDING + MARGIN_TOP + LONGEST_LABEL_LENGTH,
                                 RECT_WIDTH,
                                 RECT_HEIGHT);
            this.resultColor = calculateColor(this.medianValue);
        }

        private float[] getSignalfromBlocks()
        {
            List<float> signal = new List<float>();

            foreach (float[]block in blocks)
            {
                signal.Add(block.Max());
            }

            return signal.ToArray();
        }


        // Calculate color according to given value
        public static Color calculateColor(float value)
        {

            if (value < 0.0f)
            {
                int red = (int)(value * 255 * (-1));
                int blue = 255 - red;
                Color color = new Color();
                color = Color.FromArgb(red, 0, blue);
                return color;
            } else
            {
                int green = (int)(value * 255);
                int blue = 255 - green;
                Color color = new Color();
                color = Color.FromArgb(0, green, blue);
                return color;
            }
        }

        // Get rectangle
        public Rectangle getRectangle()
        {
            return this.rect;
        }

        // Get object color
        public Color getColor()
        {
            return this.resultColor;
        }

        // Get result signal
        public float[] getSignal()
        {
            return this.resultSignal;
        }

        // Get max value
        public float getMaxValue()
        {
            return this.maxValue;
        }

        // Get min value
        public float getMinValue()
        {
            return this.minValue;
        }

        // Get median value
        public float getMedianValue()
        {
            return this.medianValue;
        }

        // Get index of min value
        public int getMinValueIndex()
        {
            return this.indexMinValue;
        }

        // Get index of max value
        public int getMaxValueIndex()
        {
            return this.indexMaxValue;
        }

        public List<float[]> getBlocks()
        {
            return this.blocks;
        }
    }
}